home *** CD-ROM | disk | FTP | other *** search
-
- /*---------------------------------------------------------------------*\
- | |
- | CPP -- a stand-alone C preprocessor |
- | Copyright (c) 1993 Hacker Ltd. Author: Scott Bigham |
- | |
- | Permission is granted to anyone to use this software for any purpose |
- | on any computer system, and to redistribute it freely, with the |
- | following restrictions: |
- | - No charge may be made other than reasonable charges for repro- |
- | duction. |
- | - Modified versions must be clearly marked as such. |
- | - The author is not responsible for any harmful consequences of |
- | using this software, even if they result from defects therein. |
- | |
- | if_expr.c -- evaluate expression in an #if directive |
- \*---------------------------------------------------------------------*/
-
- #include <stdlib.h>
- #include <setjmp.h>
- #include <ctype.h>
- #include "global.h"
- #include "ztype.h"
-
- typedef struct {
- long l;
- char uns;
- } Long;
-
- static jmp_buf punt;
-
- static char char_const(s)
- register char *s;
- {
- char val = 0;
-
- for (; *s != '\''; s++)
- switch (*s) {
- case '\\':
- switch (*++s) {
- case 'n':
- val = '\n';
- break;
- case 't':
- val = '\t';
- break;
- case 'v':
- val = '\v';
- break;
- case 'b':
- val = '\b';
- break;
- case 'r':
- val = '\r';
- break;
- case 'f':
- val = '\f';
- break;
- case 'a':
- val = '\a';
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- val = (*s++) - '0';
- if (is_octal(*s))
- val = val << 3 + ((*s++) - '0');
- if (is_octal(*s))
- val = val << 3 + ((*s++) - '0');
- break;
- case 'x':
- val = 0;
- for (s++; isxdigit(*s); s++) {
- val = (val << 4) + (
- isdigit(*s) ? (*s - '0') :
- islower(*s) ? (*s - 'a' + 10) :
- (*s - 'A' + 10)
- );
- }
- s--;
- break;
- default:
- val = *s;
- }
- break;
- default:
- val = *s;
- }
- return val;
- }
-
- static char match(tok)
- int tok;
- {
- register TokenP T = exp_token();
- char c = T->subtype;
-
- if (T->type == tok) {
- free_token(T);
- return c;
- }
- if (tok == UNARY_OP && T->type == ADD_OP) {
- free_token(T);
- return c;
- }
- push_tlist(T);
- return '\0';
- }
-
- static void fmatch(tok)
- int tok;
- {
- if (!match(tok))
- longjmp(punt, 1);
- }
-
- static Long l_or_expr __PROTO((void));
-
- static Long primary_expr()
- {
- Long L /* ={0L,'\0'} */ ;
- register TokenP T;
-
- L.l = 0;
- L.uns = '\0';
- T = exp_token();
- switch (T->type) {
- case ID:
- free_token(T);
- return L;
- case NUMBER:
- L.l = T->val;
- L.uns == !!(T->flags & UNS_VAL);
- free_token(T);
- return L;
- case CHAR_CON:
- L.l = char_const(token_txt(T) + 1);
- free_token(T);
- return L;
- case LPAREN:
- L = l_or_expr();
- fmatch(RPAREN);
- free_token(T);
- return L;
- default:
- free_token(T);
- longjmp(punt, 1);
- }
- }
-
- static Long unary_expr()
- {
- Long L;
- char op;
-
- if (!(op = match(UNARY_OP)))
- return primary_expr();
- switch (op) {
- case '!':
- L = unary_expr();
- L.uns = 0;
- L.l = !L.l;
- return L;
- case '~':
- L = unary_expr();
- L.l = ~L.l;
- return L;
- case '+':
- return unary_expr();
- case '-':
- L = unary_expr();
- L.l = -L.l;
- return L;
- default:
- bugchk("'%c' is UNARY_OP in #if expr", op);
- longjmp(punt, 2);
- }
- }
-
- static Long mul_expr()
- {
- Long L1, L;
- char op;
-
- L1 = unary_expr();
- while (op = match(MUL_OP)) {
- L = unary_expr();
- if (L.uns)
- L1.uns = 1;
- switch (op) {
- case '*':
- L1.l *= L.l;
- break;
- case '%':
- L1.l %= L.l;
- break;
- case '/':
- if (L.l == 0) {
- error("divide by zero in #if expr");
- longjmp(punt, 2);
- }
- L1.l /= L.l;
- break;
- default:
- bugchk("'%c' is MUL_OP in #if expr", op);
- longjmp(punt, 2);
- }
- }
- return L1;
- }
-
- static Long add_expr()
- {
- Long L1, L;
- char op;
-
- L1 = mul_expr();
- while (op = match(ADD_OP)) {
- L = mul_expr();
- if (L.uns)
- L1.uns = 1;
- switch (op) {
- case '+':
- L1.l += L.l;
- break;
- case '-':
- L1.l -= L.l;
- break;
- default:
- bugchk("'%c' is ADD_OP in #if expr", op);
- longjmp(punt, 2);
- }
- }
- return L1;
- }
-
- static Long shift_expr()
- {
- Long L1, L;
- char op;
-
- L1 = add_expr();
- while (op = match(SHIFT_OP)) {
- L = add_expr();
- if (L.uns)
- L1.uns = 1;
- switch (op) {
- case '<':
- L1.l <<= L.l;
- break;
- case '>':
- L1.l >>= L.l;
- break;
- default:
- bugchk("'%c' is SHIFT_OP in #if expr", op);
- longjmp(punt, 2);
- }
- }
- return L1;
- }
-
- #define compare(L1,op,L2) \
- ((L1.uns || L2.uns) ? (unsigned long)L1.l op (unsigned long)L2.l : \
- L1.l op L2.l)
-
- static Long rel_expr()
- {
- Long L1, L;
- char op;
-
- L1 = shift_expr();
- while (op = match(REL_OP)) {
- L = shift_expr();
- switch (op) {
- case '<':
- L1.l = compare(L1, <, L);
- L1.uns = 0;
- break;
- case '>':
- L1.l = compare(L1, >, L);
- L1.uns = 0;
- break;
- case '(':
- L1.l = compare(L1, <=, L);
- L1.uns = 0;
- break;
- case ')':
- L1.l = compare(L1, >=, L);
- L1.uns = 0;
- break;
- default:
- bugchk("'%c' is REL_OP in #if expr", op);
- longjmp(punt, 2);
- }
- }
- return L1;
- }
-
- static Long eq_expr()
- {
- Long L1, L;
- char op;
-
- L1 = rel_expr();
- while ((op = match(EQ_OP))) {
- L = rel_expr();
- switch (op) {
- case '=':
- L1.l = compare(L1, ==, L);
- L1.uns = 0;
- break;
- case '!':
- L1.l = compare(L1, !=, L);
- L1.uns = 0;
- break;
- default:
- bugchk("'%c' is EQ_OP in #if expr", op);
- longjmp(punt, 2);
- }
- }
- return L1;
- }
-
- static Long b_and_expr()
- {
- Long L1, L;
- char op;
-
- L1 = eq_expr();
- while (op = match(B_AND_OP)) {
- L = eq_expr();
- if (L.uns)
- L1.uns = 1;
- switch (op) {
- case '&':
- L1.l &= L.l;
- break;
- default:
- bugchk("'%c' is B_AND_OP in #if expr", op);
- longjmp(punt, 2);
- }
- }
- return L1;
- }
-
- static Long b_xor_expr()
- {
- Long L1, L;
- char op;
-
- L1 = b_and_expr();
- while (op = match(B_XOR_OP)) {
- L = b_and_expr();
- if (L.uns)
- L1.uns = 1;
- switch (op) {
- case '^':
- L1.l ^= L.l;
- break;
- default:
- bugchk("'%c' is B_XOR_OP in #if expr", op);
- longjmp(punt, 2);
- }
- }
- return L1;
- }
-
- static Long b_or_expr()
- {
- Long L1, L;
- char op;
-
- L1 = b_xor_expr();
- while (op = match(B_OR_OP)) {
- L = b_xor_expr();
- if (L.uns)
- L1.uns = 1;
- switch (op) {
- case '|':
- L1.l |= L.l;
- break;
- default:
- bugchk("'%c' is B_OR_OP in #if expr", op);
- longjmp(punt, 2);
- }
- }
- return L1;
- }
-
- static Long l_and_expr()
- {
- Long L1, L;
- char op;
-
- L1 = b_or_expr();
- while (op = match(L_AND_OP)) {
- L = b_or_expr();
- switch (op) {
- case '&':
- L1.l = L1.l && L.l;
- L1.uns = 0;
- break;
- default:
- bugchk("'%c' is L_AND_OP in #if expr", op);
- longjmp(punt, 2);
- }
- }
- return L1;
- }
-
- static Long l_or_expr()
- {
- Long L1, L;
- char op;
-
- L1 = l_and_expr();
- while (op = match(L_OR_OP)) {
- L = l_and_expr();
- switch (op) {
- case '|':
- L1.l = L1.l || L.l;
- L1.uns = 0;
- break;
- default:
- bugchk("'%c' is L_OR_OP in #if expr", op);
- longjmp(punt, 2);
- }
- }
- return L1;
- }
-
- static Long expr()
- {
- Long L;
-
- L = l_or_expr();
- if (!match(EOL))
- longjmp(punt, 1);
- return L;
- }
-
- int if_expr()
- {
- Long L;
- int r;
-
- change_mode(IF_EXPR, 0);
- _tokenize_line();
- switch (setjmp(punt)) {
- case 0:
- L = expr();
- r = !!L.l;
- break;
- case 1:
- error("syntax error in #if expr");
- /* and fall through */
- default:
- r = 0;
- }
- change_mode(0, IF_EXPR);
- return r;
- }
-